<!DOCTYPE HTML>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /> 
    <title>深入剖析Redis客户端Jedis的特性和原理 - 天地维杰网</title>
    <meta name="keywords" content="系统架构,shutdown,不与天斗,Domino,博客,程序员,架构师,笔记,技术,分享,java,Redis">
    
    <meta property="og:title" content="深入剖析Redis客户端Jedis的特性和原理">
    <meta property="og:site_name" content="天地维杰网">
    <meta property="og:image" content="/img/author.jpg"> 
    <meta name="title" content="深入剖析Redis客户端Jedis的特性和原理 - 天地维杰网" />
    <meta name="description" content="Redis作为目前通用的缓存选型，因其高性能而倍受欢迎。Redis的2.x版本仅支持单机模式，从3.0版本开始引入集群模式。Redis的Java生态的客户端当中包含Jedis、Redisson、Lettuce，不同的客户端具备不同的能力是使用方式，本文主要分析Jedis客户端。 Jedis客户端同时支持单机模式、分片模式、集群模式的访问模式，通过构建Jedis类对象实现单机模式下的数据访问，通过构建ShardedJedis类对象实现分片模式的数据访问，通过构建JedisCluster类对象实现集群模式下的数据访问。 Jedis客户端支持单命令和Pipeline方式访问Redis集群，通过Pipeline的方式能够提高集群访问的效率。 本文的整体分析基于Jedis的3.5.0版本进行分析，相关源码均参考此版本。" />
     
    <link rel="shortcut icon" href="http://www.shutdown.cn/img/favicon.ico" />
    <link rel="apple-touch-icon" href="http://www.shutdown.cn/img/apple-touch-icon.png" />
    <link rel="apple-touch-icon-precomposed" href="http://www.shutdown.cn/img/apple-touch-icon.png" />
    <link href="http://www.shutdown.cn/js/vendor/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
    <link href="http://www.shutdown.cn/js/vendor/fancybox/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
    <link href="http://www.shutdown.cn/css/main.css" rel="stylesheet" type="text/css" />
    <link href="http://www.shutdown.cn/css/syntax.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" id="hexo.configuration">
  var NexT = window.NexT || {};
  var CONFIG = {
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post"},
     fancybox: true, 
    motion: true
  };
</script>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7826003325059020" crossorigin="anonymous"></script>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container one-collumn sidebar-position-left page-home  ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"> <div class="site-meta  custom-logo ">

  <div class="custom-logo-site-title">
    <a href="http://www.shutdown.cn"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">天地维杰网</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle">人如秋鸿来有信，事若春梦了无痕</p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
    <ul id="menu" class="menu">
      
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />首页
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/redis/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-battery-full"></i> <br />Redis
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/java/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-coffee"></i> <br />java
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/linux/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-linux"></i> <br />linux
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/daily/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-bug"></i> <br />日常问题
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/spring/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-child"></i> <br />Spring和Springboot
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/mac/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-fire"></i> <br />Mac相关
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/middleware/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-gavel"></i> <br />中间件
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/jiagou/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-rocket"></i> <br />架构
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/python/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-ship"></i> <br />python
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/front/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-bolt"></i> <br />前端
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/jvm/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-balance-scale"></i> <br />jvm
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/c/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-battery-empty"></i> <br />c语言
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/categories/web3/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-web3"></i> <br />web3
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/post/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />归档
          </a>
        </li>
      
        <li class="menu-item ">
          <a href="http://www.shutdown.cn/about/" rel="section">
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />关于
          </a>
        </li>
      
      <li class="menu-item menu-item-search">
        <a href="javascript:;" class="popup-trigger"> <i class="menu-item-icon fa fa-search fa-fw"></i> <br /> 搜索</a>
      </li>
    </ul>
    <div class="site-search">
      <div class="popup">
 <span class="search-icon fa fa-search"></span>
 <input type="text" id="local-search-input">
 <div id="local-search-result"></div>
 <span class="popup-btn-close">close</span>
</div>

    </div>
</nav>

 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            
<section id="posts" class="posts-expand">
  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <header class="post-header">
      <h1 class="post-title" itemprop="name headline">
        <a class="post-title-link" href="http://www.shutdown.cn/post/deeply-analyze-the-features-and-principles-of-redis-client-jedis/" itemprop="url">
        深入剖析Redis客户端Jedis的特性和原理
        </a>
      </h1>
      <div class="post-meta">
      <span class="post-time">
<span class="post-meta-item-icon">
    <i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">时间：</span>
<time itemprop="dateCreated" datetime="2016-03-22T13:04:35+08:00" content="2022-03-30">
    2022-03-30
</time>
</span> 
      

  <span class="post-category" >
  &nbsp; | &nbsp;
  <span class="post-meta-item-icon">
    <i class="fa fa-folder-o"></i>
  </span>
  <span class="post-meta-item-text">分类：</span>
  
    <span itemprop="about" itemscope itemtype="https://schema.org/Thing">
      <a href="http://www.shutdown.cn/categories/redis" itemprop="url" rel="index">
        <span itemprop="name">redis</span>
      </a>
      &nbsp; 
    </span>
  
</span>


      
 <span>
&nbsp; | &nbsp;
<span class="post-meta-item-icon">
    <i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">转载</span>
</span>

       <span>
&nbsp; | &nbsp;
<span class="post-meta-item-icon">
    <i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读：</span>
<span class="leancloud-visitors-count">8658 字 ~18分钟</span>
</span>
      </div>
    </header>
    <div class="post-body" itemprop="articleBody">
    
    <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-fallback" data-lang="fallback"> 文章系转载，便于整理和分类，原文地址：https://mp.weixin.qq.com/s/r3Mhk7z-1_kw31fefxEujQ</code></pre></div>
    

    

<h2 id="一-开篇">一、开篇</h2>

<p>Redis作为目前通用的缓存选型，因其高性能而倍受欢迎。Redis的2.x版本仅支持单机模式，从3.0版本开始引入集群模式。</p>

<p>Redis的Java生态的客户端当中包含Jedis、Redisson、Lettuce，不同的客户端具备不同的能力是使用方式，本文主要分析Jedis客户端。</p>

<p>Jedis客户端同时支持单机模式、分片模式、集群模式的访问模式，通过构建Jedis类对象实现单机模式下的数据访问，通过构建ShardedJedis类对象实现分片模式的数据访问，通过构建JedisCluster类对象实现集群模式下的数据访问。</p>

<p>Jedis客户端支持单命令和Pipeline方式访问Redis集群，通过Pipeline的方式能够提高集群访问的效率。</p>

<p>本文的整体分析基于Jedis的3.5.0版本进行分析，相关源码均参考此版本。</p>

<h2 id="二-jedis访问模式对比">二、Jedis访问模式对比</h2>

<p>Jedis客户端操作Redis主要分为三种模式，分表是单机模式、分片模式、集群模式。</p>

<ul>
<li><strong>单机模式</strong>主要是创建Jedis对象来操作单节点的Redis，只适用于访问单个Redis节点。</li>
<li><strong>分片模式</strong>（ShardedJedis）主要是通过创建ShardedJedisPool对象来访问分片模式的多个Redis节点，是Redis没有集群功能之前客户端实现的一个数据分布式方案，本质上是客户端通过一致性哈希来实现数据分布式存储。</li>
<li><strong>集群模式</strong>（JedisCluster）主要是通过创建JedisCluster对象来访问集群模式下的多个Redis节点，是Redis3.0引入集群模式后客户端实现的集群访问访问，本质上是通过引入槽（slot）概念以及通过CRC16哈希槽算法来实现数据分布式存储。</li>
</ul>

<p>单机模式不涉及任何分片的思想，所以我们着重分析<strong>分片模式</strong>和<strong>集群模式</strong>的理念。</p>

<h3 id="2-1-分片模式">2.1 分片模式</h3>

<ul>
<li>分片模式本质属于基于客户端的分片，在客户端实现如何根据一个key找到Redis集群中对应的节点的方案。</li>
<li>Jedis的客户端分片模式采用一致性Hash来实现，一致性Hash算法的好处是当Redis节点进行增减时只会影响新增或删除节点前后的小部分数据，相对于取模等算法来说对数据的影响范围较小。</li>
<li>Redis在大部分场景下作为缓存进行使用，所以不用考虑数据丢失致使缓存穿透造成的影响，在Redis节点增减时可以不用考虑部分数据无法命中的问题。</li>
</ul>

<p>分片模式的整体应用如下图所示，核心在于客户端的一致性Hash策略。</p>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112104652.png" width = 400 /> </div>

<p>（引用自：www.cnblogs.com）</p>

<h3 id="2-2-集群模式">2.2 集群模式</h3>

<ul>
<li>集群模式本质属于服务器分片技术，由Redis集群本身提供分片功能，从Redis 3.0版本开始正式提供。</li>
<li>集群的原理是：一个 Redis 集群包含16384 个哈希槽（Hash slot）， Redis保存的每个键都属于这16384个哈希槽的其中一个， 集群使用公式CRC16(key)%16384 来计算键 key 属于哪个槽， 其中 CRC16(key) 语句用于计算键key的CRC16校验和 。</li>
<li>集群中的每个节点负责处理一部分哈希槽。举个例子， 一个集群可以有三个哈希槽， 其中：</li>
</ul>

<blockquote>
<p>节点 A 负责处理 0 号至 5500 号哈希槽。</p>

<p>节点 B 负责处理 5501 号至 11000 号哈希槽。</p>

<p>节点 C 负责处理 11001 号至 16383 号哈希槽。</p>
</blockquote>

<ul>
<li>Redis在集群模式下对于key的读写过程首先将对应的key值进行CRC16计算得到对应的哈希值，将哈希值对槽位总数取模映射到对应的槽位，最终映射到对应的节点进行读写。以命令set(&ldquo;key&rdquo;, &ldquo;value&rdquo;)为例子，它会使用CRC16算法对key进行计算得到哈希值28989，然后对16384进行取模得到12605，最后找到12605对应的Redis节点，最终跳转到该节点执行set命令。</li>
<li>集群模式的整体应用如下图所示，核心在于集群哈希槽的设计以及重定向命令。</li>
</ul>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112104733.png" width = 300 /> </div>

<p>（引用自：<a href="https://www.jianshu.com）">https://www.jianshu.com）</a></p>

<h2 id="三-jedis的基础用法">三、Jedis的基础用法</h2>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#8f5902;font-style:italic">// Jedis单机模式的访问
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">main</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">String</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">args</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 创建Jedis对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">jedis</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;localhost&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">6379</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 执行hmget操作
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">hmget</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;foobar&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#4e9a06">&#34;foo&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 关闭Jedis对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">close</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#8f5902;font-style:italic">// Jedis分片模式的访问
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">main</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">String</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">args</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">HostAndPort</span> <span style="color:#000">redis1</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">HostAndPortUtil</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getRedisServers</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">HostAndPort</span> <span style="color:#000">redis2</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">HostAndPortUtil</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getRedisServers</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">1</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">JedisShardInfo</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">shards</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">ArrayList</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">JedisShardInfo</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">2</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">JedisShardInfo</span> <span style="color:#000">shard1</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisShardInfo</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">redis1</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">JedisShardInfo</span> <span style="color:#000">shard2</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisShardInfo</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">redis2</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 创建ShardedJedis对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">ShardedJedis</span> <span style="color:#000">shardedJedis</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">ShardedJedis</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">shards</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 通过ShardedJedis对象执行set操作
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">shardedJedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;a&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#4e9a06">&#34;bar&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#8f5902;font-style:italic">// Jedis集群模式的访问
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">main</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">String</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">args</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 构建redis的集群池
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">Set</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">nodes</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">HashSet</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">add</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;127.0.0.1&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">7001</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">add</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;127.0.0.1&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">7002</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">add</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;127.0.0.1&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">7003</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
    <span style="color:#8f5902;font-style:italic">// 创建JedisCluster
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">JedisCluster</span> <span style="color:#000">cluster</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisCluster</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
    <span style="color:#8f5902;font-style:italic">// 执行JedisCluster对象中的方法
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">cluster</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;cluster-test&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#4e9a06">&#34;my jedis cluster test&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">String</span> <span style="color:#000">result</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">cluster</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;cluster-test&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<p>Jedis通过创建Jedis的类对象来实现单机模式下的数据访问，通过构建JedisCluster类对象来实现集群模式下的数据访问。</p>

<p>要理解Jedis的访问Redis的整个过程，可以通过先理解单机模式下的访问流程，在这个基础上再分析集群模式的访问流程会比较合适。</p>

<h2 id="四-jedis单机模式的访问">四、Jedis单机模式的访问</h2>

<p>Jedis访问单机模式Redis的整体流程图如下所示，从图中可以看出核心的流程包含Jedis对象的创建以及通过Jedis对象实现Redis的访问。</p>

<p>熟悉Jedis访问单机Redis的过程，本身就是需要了解Jedis的创建过程以及执行Redis命令的过程。</p>

<ul>
<li>Jedis的创建过程核心在于创建Jedis对象以及Jedis内部变量Client对象。</li>
<li>Jedis访问Redis的过程在于通过Jedis内部的Client对象访问Redis。</li>
</ul>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112104825.png" width = 900 /> </div>

<h3 id="4-1-创建过程">4.1 创建过程</h3>

<p>Jedis本身的类关系图如下图所示，从图中我们能够看到Jedis继承自BinaryJedis类。</p>

<p>在BinaryJedis类中存在和Redis对接的Client类对象，Jedis通过父类的BinaryJedis的Client对象实现Redis的读写。</p>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112104905.png" width = 600 /> </div>

<p>Jedis类在创建过程中通过父类BinaryJedis创建了Client对象，而了解Client对象是进一步理解访问过程的关键。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Jedis</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">BinaryJedis</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">JedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">MultiKeyCommands</span><span style="color:#ce5c00;font-weight:bold">,</span>
    <span style="color:#000">AdvancedJedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ScriptingCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">BasicCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SentinelCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ModuleCommands</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">protected</span> <span style="color:#000">JedisPoolAbstract</span> <span style="color:#000">dataSource</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 创建父类BinaryJedis对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">super</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">BinaryJedis</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">BasicCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">BinaryJedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">MultiKeyBinaryCommands</span><span style="color:#ce5c00;font-weight:bold">,</span>
    <span style="color:#000">AdvancedBinaryJedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">BinaryScriptingCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#8f5902;font-style:italic">// 访问redis的Client对象
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">protected</span> <span style="color:#000">Client</span> <span style="color:#000">client</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">BinaryJedis</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 创建Client对象访问redis
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">client</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">Client</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<p>Client类的类关系图如下图所示，Client对象继承自BinaryClient和Connection类。在BinaryClient类中存在Redis访问密码等相关参数，在Connection类在存在访问Redis的socket对象以及对应的输入输出流。本质上Connection是和Redis进行通信的核心类。</p>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112104934.png" width = 600 /> </div>

<p>Client类在创建过程中初始化核心父类Connection对象，而Connection是负责和Redis直接进行通信。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Client</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">BinaryClient</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Commands</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">Client</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">super</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">BinaryClient</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">Connection</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#8f5902;font-style:italic">// 存储和Redis连接的相关信息
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">isInMulti</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">String</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">String</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">db</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">isInWatch</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">BinaryClient</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">super</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Connection</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#8f5902;font-style:italic">// 管理和Redis连接的socket信息及对应的输入输出流
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">JedisSocketFactory</span> <span style="color:#000">jedisSocketFactory</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">Socket</span> <span style="color:#000">socket</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">RedisOutputStream</span> <span style="color:#000">outputStream</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">RedisInputStream</span> <span style="color:#000">inputStream</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">infiniteSoTimeout</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">broken</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">false</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">Connection</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#000">SSLSocketFactory</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLParameters</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#000">HostnameVerifier</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 构建DefaultJedisSocketFactory来创建和Redis连接的Socket对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">DefaultJedisSocketFactory</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">host</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">port</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">Protocol</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">DEFAULT_TIMEOUT</span><span style="color:#ce5c00;font-weight:bold">,</span>
        <span style="color:#000">Protocol</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">DEFAULT_TIMEOUT</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<h3 id="4-2-访问过程">4.2 访问过程</h3>

<p>以Jedis执行set命令为例，整个过程如下：</p>

<ul>
<li>Jedis的set操作是通过Client的set操作来实现的。</li>

<li><p>Client的set操作是通过父类Connection的sendCommand来实现。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Jedis</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">BinaryJedis</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">JedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">MultiKeyCommands</span><span style="color:#ce5c00;font-weight:bold">,</span>
<span style="color:#000">AdvancedJedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ScriptingCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">BasicCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SentinelCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ModuleCommands</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#5c35cc;font-weight:bold">@Override</span>
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">String</span> <span style="color:#000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#000">checkIsInMultiOrPipeline</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#8f5902;font-style:italic">// client执行set操作
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#000">client</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">client</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getStatusCodeReply</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Client</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">BinaryClient</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Commands</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#5c35cc;font-weight:bold">@Override</span>
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#8f5902;font-style:italic">// 执行set命令
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">SafeEncoder</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">encode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SafeEncoder</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">encode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">BinaryClient</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">Connection</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#8f5902;font-style:italic">// 发送set指令
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#000">sendCommand</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">SET</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Connection</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">sendCommand</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">ProtocolCommand</span> <span style="color:#000">cmd</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#ce5c00;font-weight:bold">.</span> <span style="color:#000">args</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#8f5902;font-style:italic">// socket连接redis
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#000">connect</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#8f5902;font-style:italic">// 按照redis的协议发送命令
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#000">Protocol</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">sendCommand</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">outputStream</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">cmd</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">args</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisConnectionException</span> <span style="color:#000">ex</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div></li>
</ul>

<h2 id="五-jedis分片模式的访问">五、Jedis分片模式的访问</h2>

<p>基于前面已经介绍的Redis分片模式的一致性Hash的原理来理解Jedis的分片模式的访问。</p>

<p>关于Redis分片模式的概念：Redis在3.0版本之前没有集群模式的概念，这导致单节点能够存储的数据有限，通过Redis的客户端如Jedis在客户端通过一致性Hash算法来实现数据的分片存储。本质上Redis的分片模式跟Redis本身没有任何关系，只是通过客户端来解决单节点数据有限存储的问题。ShardedJedis访问Redis的核心在于构建对象的时候初始化一致性Hash对象，构建一致性Hash经典的Hash值和node的映射关系。构建完映射关系后执行set等操作就是Hash值到node的寻址过程，寻址完成后直接进行单节点的操作。</p>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112105008.png" width = 800 /> </div>

<h3 id="5-1-创建过程">5.1 创建过程</h3>

<p>ShardedJedis的创建过程在于父类的Sharded中关于一致性Hash相关的初始化过程，核心在于构建一致性的虚拟节点以及虚拟节点和Redis节点的映射关系。源码中最核心的部分代码在于根据根据权重映射成未160个虚拟节点，通过虚拟节点来定位到具体的Redis节点。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Sharded</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">S</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">ShardInfo</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">DEFAULT_WEIGHT</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">1</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#8f5902;font-style:italic">// 保存虚拟节点和redis的node节点的映射关系
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">TreeMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Long</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">S</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#8f5902;font-style:italic">// hash算法
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">Hashing</span> <span style="color:#000">algo</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#8f5902;font-style:italic">// 保存redis节点和访问该节点的Jedis的连接信息
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">Map</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">ShardInfo</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">resources</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">LinkedHashMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">Sharded</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">S</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">shards</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">Hashing</span> <span style="color:#000">algo</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">algo</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">algo</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">initialize</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">shards</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
 
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">initialize</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">S</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">shards</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">nodes</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">TreeMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 遍历每个redis的节点并设置hash值到节点的映射关系
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">i</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#000">i</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">shards</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">size</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#000">i</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">S</span> <span style="color:#000">shardInfo</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">shards</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">i</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#8f5902;font-style:italic">// 根据权重映射成未160个虚拟节点
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">N</span> <span style="color:#ce5c00;font-weight:bold">=</span>  <span style="color:#000">160</span> <span style="color:#ce5c00;font-weight:bold">*</span> <span style="color:#000">shardInfo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getWeight</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">shardInfo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getName</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">n</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#000">n</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span> <span style="color:#000">N</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#000">n</span><span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#8f5902;font-style:italic">// 构建hash值和节点映射关系
</span><span style="color:#8f5902;font-style:italic"></span>        <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">put</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">algo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">hash</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;SHARD-&#34;</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#000">i</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#4e9a06">&#34;-NODE-&#34;</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#000">n</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">shardInfo</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">n</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#000">n</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span> <span style="color:#000">N</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#000">n</span><span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">put</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">algo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">hash</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">shardInfo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getName</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#4e9a06">&#34;*&#34;</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#000">n</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">shardInfo</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#8f5902;font-style:italic">// 保存每个节点的访问对象
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">resources</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">put</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">shardInfo</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">shardInfo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">createResource</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<h3 id="5-2-访问过程">5.2 访问过程</h3>

<p>ShardedJedis的访问过程就是一致性Hash的计算过程，核心的逻辑就是：通过Hash算法对访问的key进行Hash计算生成Hash值，根据Hash值获取对应Redis节点，根据对应的Redis节点获取对应的访问对象Jedis。获取访问对象Jedis之后就可以直接进行命令操作。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Sharded</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">S</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">ShardInfo</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">DEFAULT_WEIGHT</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">1</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">TreeMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Long</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">S</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">Hashing</span> <span style="color:#000">algo</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#8f5902;font-style:italic">// 保存redis节点和访问该节点的Jedis的连接信息
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">Map</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">ShardInfo</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">R</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">resources</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">LinkedHashMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">R</span> <span style="color:#000">getShard</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">String</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 根据redis节点找到对应的访问对象Jedis
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">resources</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">getShardInfo</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">S</span> <span style="color:#000">getShardInfo</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">String</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">getShardInfo</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">SafeEncoder</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">encode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">getKeyTag</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">S</span> <span style="color:#000">getShardInfo</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 针对访问的key生成对应的hash值
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#8f5902;font-style:italic">// 根据hash值找到对应的redis节点
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">SortedMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Long</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">S</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">tail</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">tailMap</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">algo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">hash</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">tail</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">isEmpty</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">firstKey</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">tail</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">tail</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">firstKey</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<h2 id="六-jedis集群模式的访问">六、Jedis集群模式的访问</h2>

<p>基于前面介绍的Redis的集群原理来理解Jedis的集群模式的访问。</p>

<p>Jedis能够实现key和哈希槽的定位的核心机制在于哈希槽和Redis节点的映射，而这个发现过程基于Redis的cluster slot命令。</p>

<p>关于Redis集群操作的命令：Redis通过cluster slots会返回Redis集群的整体状况。返回每一个Redis节点的信息包含：</p>

<ul>
<li>哈希槽起始编号</li>
<li>哈希槽结束编号</li>
<li>哈希槽对应master节点，节点使用IP/Port表示</li>
<li>master节点的第一个副本</li>

<li><p>master节点的第二个副本</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">127.0.0.1:30001&gt; cluster slots
1<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">0</span> // 开始槽位
2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">5460</span> // 结束槽位
3<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;127.0.0.1&#34;</span> // master节点的host
  2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">30001</span> // master节点的port
  3<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;09dbe9720cda62f7865eabc5fd8857c5d2678366&#34;</span> // 节点的编码
4<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;127.0.0.1&#34;</span> // slave节点的host
  2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">30004</span> // slave节点的port
  3<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;821d8ca00d7ccf931ed3ffc7e3db0599d2271abf&#34;</span> // 节点的编码
2<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">5461</span>
2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">10922</span>
3<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;127.0.0.1&#34;</span>
  2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">30002</span>
  3<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;c9d93d9f2c0c524ff34cc11838c2003d8c29e013&#34;</span>
4<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;127.0.0.1&#34;</span>
  2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">30005</span>
  3<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;faadb3eb99009de4ab72ad6b6ed87634c7ee410f&#34;</span>
3<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">10923</span>
2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">16383</span>
3<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;127.0.0.1&#34;</span>
  2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">30003</span>
  3<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;044ec91f325b7595e76dbcb18cc688b6a5b434a1&#34;</span>
4<span style="color:#ce5c00;font-weight:bold">)</span> 1<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;127.0.0.1&#34;</span>
  2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">(</span>integer<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#0000cf;font-weight:bold">30006</span>
  3<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#4e9a06">&#34;58e6e48d41228013e5d9c1c37c5060693925e97e&#34;</span></code></pre></div></li>
</ul>

<p>Jedis访问集群模式Redis的整体流程图如下所示，从图中可以看出核心的流程包含JedisCluster对象的创建以及通过JedisCluster对象实现Redis的访问。</p>

<p>JedisCluster对象的创建核心在于创建JedisClusterInfoCache对象并通过集群发现来建立slot和集群节点的映射关系。</p>

<p>JedisCluster对Redis集群的访问在于获取key所在的Redis节点并通过Jedis对象进行访问。</p>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112105047.png" width = 900 /> </div>

<h3 id="6-1-创建过程">6.1 创建过程</h3>

<p>JedisCluster的类关系如下图所示，在图中可以看到核心变量JedisSlotBasedConnectionHandler对象。</p>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112105108.png" width = 400 /> </div>

<p>JedisCluster的父类BinaryJedisCluster创建了JedisSlotBasedConnectionHandler对象，该对象负责和Redis的集群进行通信。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisCluster</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">BinaryJedisCluster</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">JedisClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span>
    <span style="color:#000">MultiKeyJedisClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisClusterScriptingCommands</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">JedisCluster</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Set</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">jedisClusterNode</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">maxAttempts</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">GenericObjectPoolConfig</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLSocketFactory</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLParameters</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#000">HostnameVerifier</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisClusterHostAndPortMap</span> <span style="color:#000">hostAndPortMap</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
    <span style="color:#8f5902;font-style:italic">// 访问父类BinaryJedisCluster
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">super</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">jedisClusterNode</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">maxAttempts</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span>
        <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostAndPortMap</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">BinaryJedisCluster</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">BinaryJedisClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span>
    <span style="color:#000">MultiKeyBinaryJedisClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisClusterBinaryScriptingCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">BinaryJedisCluster</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Set</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">jedisClusterNode</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">maxAttempts</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">GenericObjectPoolConfig</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLSocketFactory</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLParameters</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#000">HostnameVerifier</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisClusterHostAndPortMap</span> <span style="color:#000">hostAndPortMap</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
    <span style="color:#8f5902;font-style:italic">// 创建JedisSlotBasedConnectionHandler对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">connectionHandler</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisSlotBasedConnectionHandler</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">jedisClusterNode</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span>
        <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostAndPortMap</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
    <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">maxAttempts</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">maxAttempts</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<p>JedisSlotBasedConnectionHandler的核心在于创建并初始化JedisClusterInfoCache对象，该对象缓存了Redis集群的信息。</p>

<p>JedisClusterInfoCache对象的初始化过程通过initializeSlotsCache来完成，主要目的用于实现集群节点和槽位发现。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisSlotBasedConnectionHandler</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">JedisClusterConnectionHandler</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">JedisSlotBasedConnectionHandler</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Set</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">GenericObjectPoolConfig</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLSocketFactory</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLParameters</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#000">HostnameVerifier</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisClusterHostAndPortMap</span> <span style="color:#000">portMap</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
    <span style="color:#204a87;font-weight:bold">super</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span>
        <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">portMap</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">abstract</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisClusterConnectionHandler</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">JedisClusterConnectionHandler</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Set</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">GenericObjectPoolConfig</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">infiniteSoTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLSocketFactory</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLParameters</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#000">HostnameVerifier</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisClusterHostAndPortMap</span> <span style="color:#000">portMap</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
    <span style="color:#8f5902;font-style:italic">// 创建JedisClusterInfoCache对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">cache</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisClusterInfoCache</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">infiniteSoTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span>
        <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">portMap</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
    <span style="color:#8f5902;font-style:italic">// 初始化jedis的Slot信息
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">initializeSlotsCache</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">infiniteSoTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span>
        <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
 
 
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">initializeSlotsCache</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Set</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">HostAndPort</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">startNodes</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">infiniteSoTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">String</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span>
      <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLSocketFactory</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">SSLParameters</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">HostnameVerifier</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">HostAndPort</span> <span style="color:#000">hostAndPort</span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#000">startNodes</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
      <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Jedis</span> <span style="color:#000">jedis</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">hostAndPort</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getHost</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostAndPort</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span>
          <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">infiniteSoTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
        <span style="color:#8f5902;font-style:italic">// 通过discoverClusterNodesAndSlots进行集群发现
</span><span style="color:#8f5902;font-style:italic"></span>        <span style="color:#000">cache</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">discoverClusterNodesAndSlots</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#204a87;font-weight:bold">return</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisConnectionException</span> <span style="color:#000">e</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<p>JedisClusterInfoCache的nodes用来保存Redis集群的节点信息，slots用来保存槽位和集群节点的信息。</p>

<p>nodes和slots维持的对象都是JedisPool对象，该对象维持了和Redis的连接信息。集群的发现过程由discoverClusterNodesAndSlots来实现，本质是执行Redis的集群发现命令cluster slots实现的。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisClusterInfoCache</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#8f5902;font-style:italic">// 负责保存redis集群的节点信息
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">Map</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">String</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisPool</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">nodes</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">HashMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#8f5902;font-style:italic">// 负责保存redis的槽位和redis节点的映射关系
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">Map</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Integer</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisPool</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">slots</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">HashMap</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#8f5902;font-style:italic">// 负责集群的发现逻辑
</span><span style="color:#8f5902;font-style:italic"></span>  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">discoverClusterNodesAndSlots</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Jedis</span> <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">w</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">lock</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
    <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">reset</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">slots</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">clusterSlots</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
      <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Object</span> <span style="color:#000">slotInfoObj</span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#000">slots</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">slotInfo</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#000">slotInfoObj</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
        <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slotInfo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">size</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">MASTER_NODE_INDEX</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
          <span style="color:#204a87;font-weight:bold">continue</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#ce5c00;font-weight:bold">}</span>
        <span style="color:#8f5902;font-style:italic">// 获取redis节点对应的槽位信息
</span><span style="color:#8f5902;font-style:italic"></span>        <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Integer</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">slotNums</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">getAssignedSlotArray</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slotInfo</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
        <span style="color:#8f5902;font-style:italic">// hostInfos
</span><span style="color:#8f5902;font-style:italic"></span>        <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">size</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">slotInfo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">size</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">i</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">MASTER_NODE_INDEX</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#000">i</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span> <span style="color:#000">size</span><span style="color:#ce5c00;font-weight:bold">;</span> <span style="color:#000">i</span><span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#ce5c00;font-weight:bold">+</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
          <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">hostInfos</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#000">slotInfo</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">i</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
          <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">hostInfos</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">isEmpty</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
            <span style="color:#204a87;font-weight:bold">continue</span><span style="color:#ce5c00;font-weight:bold">;</span>
          <span style="color:#ce5c00;font-weight:bold">}</span>
 
          <span style="color:#000">HostAndPort</span> <span style="color:#000">targetNode</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">generateHostAndPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">hostInfos</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
          <span style="color:#8f5902;font-style:italic">// 负责保存redis节点信息
</span><span style="color:#8f5902;font-style:italic"></span>          <span style="color:#000">setupNodeIfNotExist</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">targetNode</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
          <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">i</span> <span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">MASTER_NODE_INDEX</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
            <span style="color:#8f5902;font-style:italic">// 负责保存槽位和redis节点的映射关系
</span><span style="color:#8f5902;font-style:italic"></span>            <span style="color:#000">assignSlotsToNode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slotNums</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">targetNode</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
          <span style="color:#ce5c00;font-weight:bold">}</span>
        <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">finally</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">w</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">unlock</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">assignSlotsToNode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Integer</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">targetSlots</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">HostAndPort</span> <span style="color:#000">targetNode</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">w</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">lock</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">JedisPool</span> <span style="color:#000">targetPool</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">setupNodeIfNotExist</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">targetNode</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#8f5902;font-style:italic">// 保存槽位和对应的JedisPool对象
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Integer</span> <span style="color:#000">slot</span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#000">targetSlots</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">slots</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">put</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">targetPool</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">finally</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">w</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">unlock</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">JedisPool</span> <span style="color:#000">setupNodeIfNotExist</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">HostAndPort</span> <span style="color:#000">node</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">w</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">lock</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#8f5902;font-style:italic">// 生产redis节点对应的nodeKey
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">String</span> <span style="color:#000">nodeKey</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">getNodeKey</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">node</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#000">JedisPool</span> <span style="color:#000">existingPool</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">nodeKey</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">existingPool</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">existingPool</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#8f5902;font-style:italic">// 生产redis节点对应的JedisPool
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">JedisPool</span> <span style="color:#000">nodePool</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisPool</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">node</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getHost</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">node</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span>
          <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">infiniteSoTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">,</span>
          <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#8f5902;font-style:italic">// 保存redis节点的key和对应的JedisPool对象
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">nodes</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">put</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">nodeKey</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">nodePool</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">nodePool</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">finally</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">w</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">unlock</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<p>JedisPool的类关系如下图所示，其中内部internalPool是通过apache common pool来实现的池化。</p>

<div  align="center"><img src="https://wejack639.oss-cn-beijing.aliyuncs.com/blogimages/img/20211112105148.png" width = 600 /> </div>

<p>JedisPool内部的internalPool通过JedisFactory的makeObject来创建Jedis对象。</p>

<p>每个Redis节点都会对应一个JedisPool对象，通过JedisPool来管理Jedis的申请释放复用等。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisPool</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">JedisPoolAbstract</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">JedisPool</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Protocol</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">DEFAULT_HOST</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">Protocol</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">DEFAULT_PORT</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisPoolAbstract</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">Pool</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">JedisPoolAbstract</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">super</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">abstract</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Pool</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">protected</span> <span style="color:#000">GenericObjectPool</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">internalPool</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">initPool</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">GenericObjectPoolConfig</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">PooledObjectFactory</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">factory</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">internalPool</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">closeInternalPool</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Exception</span> <span style="color:#000">e</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">internalPool</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">GenericObjectPool</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">factory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">poolConfig</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
<span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisFactory</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">PooledObjectFactory</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#ce5c00;font-weight:bold">{</span>
   
  <span style="color:#5c35cc;font-weight:bold">@Override</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">PooledObject</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">makeObject</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#204a87;font-weight:bold">throws</span> <span style="color:#000">Exception</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 创建Jedis对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">HostAndPort</span> <span style="color:#000">hp</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">hostAndPort</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">Jedis</span> <span style="color:#000">jedis</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">hp</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getHost</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hp</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">connectionTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">soTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span>
        <span style="color:#000">infiniteSoTimeout</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">ssl</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslSocketFactory</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">sslParameters</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hostnameVerifier</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
    <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#8f5902;font-style:italic">// Jedis对象连接
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">connect</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">user</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">auth</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">user</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">password</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">auth</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">password</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">database</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">select</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">database</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">clientName</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">clientSetname</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">clientName</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisException</span> <span style="color:#000">je</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">close</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">throw</span> <span style="color:#000">je</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#8f5902;font-style:italic">// 将Jedis对象包装成DefaultPooledObject进行返回
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">DefaultPooledObject</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<h3 id="6-2-访问过程">6.2 访问过程</h3>

<p>JedisCluster访问Redis的过程通过JedisClusterCommand来实现重试机制，最终通过Jedis对象来实现访问。</p>

<p>从实现的角度来说JedisCluster是在Jedis之上封装了一层，进行集群节点定位以及重试机制等。</p>

<p>以set命令为例，整个访问通过JedisClusterCommand实现如下：</p>

<ul>
<li>计算key所在的Redis节点。</li>
<li>获取Redis节点对应的Jedis对象。</li>

<li><p>通过Jedis对象进行set操作。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisCluster</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">BinaryJedisCluster</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">JedisClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span>
<span style="color:#000">MultiKeyJedisClusterCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisClusterScriptingCommands</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
<span style="color:#5c35cc;font-weight:bold">@Override</span>
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">String</span> <span style="color:#000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">SetParams</span> <span style="color:#000">params</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
<span style="color:#204a87;font-weight:bold">return</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisClusterCommand</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">String</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connectionHandler</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">maxAttempts</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#5c35cc;font-weight:bold">@Override</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">String</span> <span style="color:#000">execute</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Jedis</span> <span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">params</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">run</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div></li>
</ul>

<p>JedisClusterCommand的run方法核心主要定位Redis的key所在的Redis节点，然后获取与该节点对应的Jedis对象进行访问。</p>

<p>在Jedis对象访问异常后，JedisClusterCommand会进行重试操作并按照一定策略执行renewSlotCache方法进行重集群节点重发现动作。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">abstract</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisClusterCommand</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">T</span> <span style="color:#000">run</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">String</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 针对key进行槽位的计算
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">runWithRetries</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisClusterCRC16</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getSlot</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">maxAttempts</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">false</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
   
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">T</span> <span style="color:#000">runWithRetries</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">attempts</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">boolean</span> <span style="color:#000">tryRandomNode</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">JedisRedirectionException</span> <span style="color:#000">redirect</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
    <span style="color:#000">Jedis</span> <span style="color:#000">connection</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">redirect</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#000">connection</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">connectionHandler</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getConnectionFromNode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">redirect</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getTargetNode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">redirect</span> <span style="color:#204a87;font-weight:bold">instanceof</span> <span style="color:#000">JedisAskDataException</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
          <span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">asking</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">tryRandomNode</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
          <span style="color:#000">connection</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">connectionHandler</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getConnection</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span>
          <span style="color:#8f5902;font-style:italic">// 根据slot去获取Jedis对象
</span><span style="color:#8f5902;font-style:italic"></span>          <span style="color:#000">connection</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">connectionHandler</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getConnectionFromSlot</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#8f5902;font-style:italic">// 执行真正的Redis的命令
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">execute</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisNoReachableClusterNodeException</span> <span style="color:#000">jnrcne</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#204a87;font-weight:bold">throw</span> <span style="color:#000">jnrcne</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisConnectionException</span> <span style="color:#000">jce</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
      <span style="color:#000">releaseConnection</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#000">connection</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">attempts</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">1</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#8f5902;font-style:italic">// 保证最后两次机会去重新刷新槽位和节点的对应的信息
</span><span style="color:#8f5902;font-style:italic"></span>        <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">connectionHandler</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">renewSlotCache</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#8f5902;font-style:italic">// 按照重试次数进行重试操作
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">runWithRetries</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">attempts</span> <span style="color:#ce5c00;font-weight:bold">-</span> <span style="color:#000">1</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">tryRandomNode</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">redirect</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisRedirectionException</span> <span style="color:#000">jre</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#8f5902;font-style:italic">// 针对返回Move命令立即触发重新刷新槽位和节点的对应信息
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">jre</span> <span style="color:#204a87;font-weight:bold">instanceof</span> <span style="color:#000">JedisMovedDataException</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#8f5902;font-style:italic">// it rebuilds cluster&#39;s slot cache recommended by Redis cluster specification
</span><span style="color:#8f5902;font-style:italic"></span>        <span style="color:#204a87;font-weight:bold">this</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">connectionHandler</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">renewSlotCache</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
 
      <span style="color:#000">releaseConnection</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#000">connection</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">runWithRetries</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">attempts</span> <span style="color:#ce5c00;font-weight:bold">-</span> <span style="color:#000">1</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">false</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">jre</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">finally</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">releaseConnection</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connection</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<p>JedisSlotBasedConnectionHandler的cache对象维持了slot和node的映射关系，通过getConnectionFromSlot方法来获取该slot对应的Jedis对象。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">JedisSlotBasedConnectionHandler</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">JedisClusterConnectionHandler</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">protected</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">JedisClusterInfoCache</span> <span style="color:#000">cache</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
  <span style="color:#5c35cc;font-weight:bold">@Override</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">Jedis</span> <span style="color:#000">getConnectionFromSlot</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">int</span> <span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 获取槽位对应的JedisPool对象
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">JedisPool</span> <span style="color:#000">connectionPool</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">cache</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getSlotPool</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connectionPool</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#8f5902;font-style:italic">// 从JedisPool对象中获取Jedis对象
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">connectionPool</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getResource</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#8f5902;font-style:italic">// 获取失败就重新刷新槽位信息
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">renewSlotCache</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#000">connectionPool</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">cache</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getSlotPool</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">slot</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">connectionPool</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">connectionPool</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getResource</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#8f5902;font-style:italic">//no choice, fallback to new connection to random node
</span><span style="color:#8f5902;font-style:italic"></span>        <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">getConnection</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<h2 id="七-jedis的pipeline实现">七、Jedis的Pipeline实现</h2>

<p>Pipeline的技术核心思想是将多个命令发送到服务器而不用等待回复，最后在一个步骤中读取该答复。这种模式的好处在于节省了请求响应这种模式的网络开销。</p>

<p>Redis的普通命令如set和Pipeline批量操作的核心的差别在于set命令的操作会直接发送请求到Redis并同步等待结果返回，而Pipeline的操作会发送请求但不立即同步等待结果返回，具体的实现可以从Jedis的源码一探究竟。</p>

<p>原生的Pipeline在集群模式下相关的key必须Hash到同一个节点才能生效，原因在于Pipeline下的Client对象只能其中的一个节点建立了连接。</p>

<p>在集群模式下归属于不同节点的key能够使用Pipeline就需要针对每个key保存对应的节点的client对象，在最后执行获取数据的时候一并获取。本质上可以认为在单节点的Pipeline的基础上封装成一个集群式的Pipeline。</p>

<h3 id="7-1-pipeline用法分析">7.1 Pipeline用法分析</h3>

<p>Pipeline访问单节点的Redis的时候，通过Jedis对象的Pipeline方法返回Pipeline对象，其他的命令操作通过该Pipeline对象进行访问。</p>

<p>Pipeline从使用角度来分析，会批量发送多个命令并最后统一使用syncAndReturnAll来一次性返回结果。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">pipeline</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">jedis</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">Jedis</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">hnp</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getHost</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">hnp</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getPort</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">500</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">Pipeline</span> <span style="color:#000">p</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">jedis</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">pipelined</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 批量发送命令到redis
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">p</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;foo&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#4e9a06">&#34;bar&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">p</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;foo&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 同步等待响应结果
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">results</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">p</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">syncAndReturnAll</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 
    <span style="color:#000">assertEquals</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">2</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">results</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">size</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">assertEquals</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;OK&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">results</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#000">assertEquals</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;bar&#34;</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">results</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">1</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
 <span style="color:#ce5c00;font-weight:bold">}</span>
 
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">abstract</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">PipelineBase</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">Queable</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">BinaryRedisPipeline</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">RedisPipeline</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#5c35cc;font-weight:bold">@Override</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">Response</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">String</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#000">String</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 发送命令
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">getClient</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// pipeline的getResponse只是把待响应的请求聚合到pipelinedResponses对象当中
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">getResponse</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">BuilderFactory</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">STRING</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Queable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">private</span> <span style="color:#000">Queue</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Response</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">?</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">pipelinedResponses</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">LinkedList</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#204a87;font-weight:bold">protected</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">Response</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">getResponse</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Builder</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">builder</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">Response</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">T</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">lr</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">Response</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">builder</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 统一保存到响应队列当中
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">pipelinedResponses</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">add</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">lr</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">lr</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Pipeline</span> <span style="color:#204a87;font-weight:bold">extends</span> <span style="color:#000">MultiKeyPipelineBase</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">syncAndReturnAll</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">getPipelinedResponseLength</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">0</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#8f5902;font-style:italic">// 根据批量发送命令的个数即需要批量返回命令的个数，通过client对象进行批量读取
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">unformatted</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">client</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getMany</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">getPipelinedResponseLength</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#000">List</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">formatted</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">ArrayList</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">Object</span> <span style="color:#000">o</span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#000">unformatted</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
        <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
          <span style="color:#8f5902;font-style:italic">// 格式化每个返回的结果并最终保存在列表中进行返回
</span><span style="color:#8f5902;font-style:italic"></span>          <span style="color:#000">formatted</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">add</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">generateResponse</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">o</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">get</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">JedisDataException</span> <span style="color:#000">e</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
          <span style="color:#000">formatted</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">add</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">e</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
        <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#ce5c00;font-weight:bold">}</span>
      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">formatted</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">java</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">util</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">Collections</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">Object</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">emptyList</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<p>普通set命令发送请求给Redis后立即通过getStatusCodeReply来获取响应结果，所以这是一种请求响应的模式。getStatusCodeReply在获取响应结果的时候会通过flush()命令强制发送报文到Redis服务端然后通过读取响应结果。</p>
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">BinaryJedis</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">BasicCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">BinaryJedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">MultiKeyBinaryCommands</span><span style="color:#ce5c00;font-weight:bold">,</span>
    <span style="color:#000">AdvancedBinaryJedisCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">BinaryScriptingCommands</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
 
  <span style="color:#5c35cc;font-weight:bold">@Override</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">String</span> <span style="color:#000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#000">checkIsInMultiOrPipeline</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 发送命令
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">client</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">set</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">key</span><span style="color:#ce5c00;font-weight:bold">,</span> <span style="color:#000">value</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 等待请求响应
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">client</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">getStatusCodeReply</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Connection</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">public</span> <span style="color:#000">String</span> <span style="color:#000">getStatusCodeReply</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#8f5902;font-style:italic">// 通过flush立即发送请求
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#000">flush</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#8f5902;font-style:italic">// 处理响应请求
</span><span style="color:#8f5902;font-style:italic"></span>    <span style="color:#204a87;font-weight:bold">final</span> <span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#000">resp</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">byte</span><span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#ce5c00;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#000">readProtocolWithCheckingBroken</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">null</span> <span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">resp</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#204a87;font-weight:bold">null</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">SafeEncoder</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">encode</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">resp</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span>
 
 
<span style="color:#204a87;font-weight:bold">public</span> <span style="color:#204a87;font-weight:bold">class</span> <span style="color:#000">Connection</span> <span style="color:#204a87;font-weight:bold">implements</span> <span style="color:#000">Closeable</span> <span style="color:#ce5c00;font-weight:bold">{</span>
  <span style="color:#204a87;font-weight:bold">protected</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">flush</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
    <span style="color:#204a87;font-weight:bold">try</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#8f5902;font-style:italic">// 针对输出流进行flush操作保证报文的发出
</span><span style="color:#8f5902;font-style:italic"></span>      <span style="color:#000">outputStream</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#c4a000">flush</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">catch</span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">IOException</span> <span style="color:#000">ex</span><span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span>
      <span style="color:#000">broken</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">true</span><span style="color:#ce5c00;font-weight:bold">;</span>
      <span style="color:#204a87;font-weight:bold">throw</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">JedisConnectionException</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">ex</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">;</span>
    <span style="color:#ce5c00;font-weight:bold">}</span>
  <span style="color:#ce5c00;font-weight:bold">}</span>
<span style="color:#ce5c00;font-weight:bold">}</span></code></pre></div>
<h2 id="八-结束语">八、结束语</h2>

<p>Jedis作为Redis官方首选的Java客户端开发包，支持绝大部分的Redis的命令，也是日常中使用较多的Redis客户端。</p>

<p>了解了Jedis的实现原理，除了能够支持Redis的日常操作外，还能更好的应对Redis的额外操作诸如扩容时的技术选型。</p>

<p>通过介绍Jedis针对单机模式、分配模式、集群模式三种场景访问方式，让大家有个从宏观到微观的理解过程，掌握Jedis的核心思想并更好的应用到实践当中。</p>

    </div>
    <footer class="post-footer">
     
 
<div class="post-tags">     
     
    <a href="http://www.shutdown.cn/tags/redis" rel="tag" title="redis">#redis#</a>
    
    <a href="http://www.shutdown.cn/tags/%e5%ae%a2%e6%88%b7%e7%ab%af" rel="tag" title="客户端">#客户端#</a>
    
    <a href="http://www.shutdown.cn/tags/jedis" rel="tag" title="jedis">#jedis#</a>
    
    <a href="http://www.shutdown.cn/tags/%e7%89%b9%e6%80%a7" rel="tag" title="特性">#特性#</a>
    
    <a href="http://www.shutdown.cn/tags/%e5%8e%9f%e7%90%86" rel="tag" title="原理">#原理#</a>
    
</div>



     <div class="post-nav">
    <div class="post-nav-next post-nav-item">
    
        <a href="http://www.shutdown.cn/post/etcd-large-scale-service-governance/" rel="next" title="基于etcd实现大规模服务治理应用实战">
        <i class="fa fa-chevron-left"></i> 基于etcd实现大规模服务治理应用实战
        </a>
    
    </div>

    <div class="post-nav-prev post-nav-item">
    
        <a href="http://www.shutdown.cn/post/mac-vmware-install-redis/" rel="prev" title=" Mac VMWARE 安装redis">
         Mac VMWARE 安装redis <i class="fa fa-chevron-right"></i>
        </a>
    
    </div>
</div>
      
     
     
     






    </footer>
  </article>
</section>

          </div>
        </div>
        <div class="sidebar-toggle">
  <div class="sidebar-toggle-line-wrap">
    <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
    <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
    <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
  </div>
</div>
<aside id="sidebar" class="sidebar">
  <div class="sidebar-inner">

  <ul class="sidebar-nav motion-element">
    <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
      文章目录
    </li>
    <li class="sidebar-nav-overview" data-target="site-overview">
      站点概览
    </li>
  </ul>

    <section class="site-overview sidebar-panel ">
      <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image"
        src="http://www.shutdown.cn/img/author.jpg"
        alt="不与天斗Domino" />
    <p class="site-author-name" itemprop="name">不与天斗Domino</p>
    <p class="site-description motion-element" itemprop="description"> 
        Programmer &amp; Architect</p>
</div>
      <nav class="site-state motion-element">
    <div class="site-state-item site-state-posts">
      <a href="http://www.shutdown.cn/post/">
        <span class="site-state-item-count">183</span>
        <span class="site-state-item-name">日志</span>
      </a>
    </div>
    <div class="site-state-item site-state-categories">    
        <a href="http://www.shutdown.cn/categories/">      
         
        <span class="site-state-item-count">15</span>
        
        <span class="site-state-item-name">分类</span>
        
        </a>
    </div>

    <div class="site-state-item site-state-tags">
        <a href="http://www.shutdown.cn/tags/">
         
        <span class="site-state-item-count">224</span>
        
        <span class="site-state-item-name">标签</span>
        </a>
    </div>
</nav>
      
      

      

      <div class="links-of-blogroll motion-element inline">
<script type="text/javascript" src="//rf.revolvermaps.com/0/0/8.js?i=&amp;m=0&amp;s=220&amp;c=ff0000&amp;cr1=ffffff&amp;f=arial&amp;l=33&amp;bv=35" async="async"></script>
</div>

    </section>
    
<section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
    <div class="post-toc">
        <div class="post-toc-content"><nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#一-开篇">一、开篇</a></li>
<li><a href="#二-jedis访问模式对比">二、Jedis访问模式对比</a>
<ul>
<li><a href="#2-1-分片模式">2.1 分片模式</a></li>
<li><a href="#2-2-集群模式">2.2 集群模式</a></li>
</ul></li>
<li><a href="#三-jedis的基础用法">三、Jedis的基础用法</a></li>
<li><a href="#四-jedis单机模式的访问">四、Jedis单机模式的访问</a>
<ul>
<li><a href="#4-1-创建过程">4.1 创建过程</a></li>
<li><a href="#4-2-访问过程">4.2 访问过程</a></li>
</ul></li>
<li><a href="#五-jedis分片模式的访问">五、Jedis分片模式的访问</a>
<ul>
<li><a href="#5-1-创建过程">5.1 创建过程</a></li>
<li><a href="#5-2-访问过程">5.2 访问过程</a></li>
</ul></li>
<li><a href="#六-jedis集群模式的访问">六、Jedis集群模式的访问</a>
<ul>
<li><a href="#6-1-创建过程">6.1 创建过程</a></li>
<li><a href="#6-2-访问过程">6.2 访问过程</a></li>
</ul></li>
<li><a href="#七-jedis的pipeline实现">七、Jedis的Pipeline实现</a>
<ul>
<li><a href="#7-1-pipeline用法分析">7.1 Pipeline用法分析</a></li>
</ul></li>
<li><a href="#八-结束语">八、结束语</a></li>
</ul></li>
</ul>
</nav></div>
    </div>
</section>

  </div>
</aside>

      </div>
    </main>
   
    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  <span itemprop="copyrightYear">  &copy; 
  2013 - 2023</span>
  <span class="with-love"><i class="fa fa-heart"></i></span>
  <span class="author" itemprop="copyrightHolder">天地维杰网</span>
  <span class="icp" itemprop="copyrightHolder"><a href="https://beian.miit.gov.cn/" target="_blank">京ICP备13019191号-1</a></span>
</div>
<div class="powered-by">
  Powered by - <a class="theme-link" href="http://gohugo.io" target="_blank" title="hugo" >Hugo v0.63.2</a>
</div>
<div class="theme-info">
  Theme by - <a class="theme-link" href="https://github.com/xtfly/hugo-theme-next" target="_blank"> NexT
  </a>
</div>


      </div>
    </footer>

    <div class="back-to-top">
      <i class="fa fa-arrow-up"></i>
      <span id="scrollpercent"><span>0</span>%</span>
    </div>
  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>
<script type="text/javascript" src="http://www.shutdown.cn/js/vendor/jquery/index.js?v=2.1.3"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/vendor/fastclick/lib/fastclick.min.js?v=1.0.6"></script> 
<script type="text/javascript" src="http://www.shutdown.cn/js/vendor/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/vendor/velocity/velocity.min.js?v=1.2.1"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/vendor/velocity/velocity.ui.min.js?v=1.2.1"></script>
<script src="http://www.shutdown.cn/js/vendor/ua-parser-js/dist/ua-parser.min.js?v=0.7.9"></script>

<script src="http://www.shutdown.cn/js/vendor/fancybox/jquery.fancybox.pack.js?v=2.1.5"></script>

<script type="text/javascript" src="http://www.shutdown.cn/js/utils.js"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/motion.js"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/affix.js"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/schemes/pisces.js"></script>

<script type="text/javascript" src="http://www.shutdown.cn/js/scrollspy.js"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/post-details.js"></script>
<script type="text/javascript" src="http://www.shutdown.cn/js/toc.js"></script>

<script type="text/javascript" src="http://www.shutdown.cn/js/bootstrap.js"></script>

<script type="text/javascript" src="http://www.shutdown.cn/js/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js"],
    jax: ["input/TeX", "output/HTML-CSS"],
    tex2jax: {
      inlineMath: [ ['$','$'] ],
      displayMath: [ ['$$','$$'] ],
      processEscapes: true
    },
    "HTML-CSS": { fonts: ["TeX"] }
  });
</script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML' async></script>
</body>
</html>